package com.gzy.gameserver;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.sql.ResultSet;
import java.io.Serializable;

import com.gzy.protocol.PlayerProtocol;
import com.sun.sgs.app.*;

import java.awt.geom.Point2D;

import com.gamalocus.sgs.services.mysql.MySQLManager;

/**
 * 
 * @author gzy : the player class {@link World}
 *
 */

public class Player
	implements ClientSessionListener, Serializable
{

	/**The version of the serialized form of this class */
	private static final long serialVersionUID = 1L;
	
	private static final Logger logger = Logger.getLogger(Player.class.getName());
	
	public static final String MESSAGE_CHARSET = "UTF-8";
	
	protected static final String PLAYER_BIND_PREFIX = "Player.";
	
	private ManagedReference<ClientSession> currentSessionRef;
	
	private ManagedReference<World> currentWorldRef;
	private ManagedReference<Pawn> currentPawnRef;
	
	private String name;

	private int PERIOD_MS = 500;
	
	/** Player properties */
	protected Point2D.Float location = new Point2D.Float(240, 160);
	protected int 		  lifePoint = 100; 
	
	protected int	playerID;
	
	public static Player loggedIn(ClientSession session)
	{
		String pawnName = "default";
		try
		{
			MySQLManager myman = AppContext.getManager(MySQLManager.class);
			//myman.executeSQL("account update", "UPDATE account SET credit=21 WHERE id=1001");
			ResultSet res = myman.executeSelect(String.format("SELECT * from players WHERE id='%s'", session.getName()));
			if(res.next())
			{
				pawnName = res.getString(2);
				logger.log(Level.INFO, "pawn name = {0}", pawnName);
			}
		}
		catch(Exception e)
		{
			logger.log(Level.INFO, "{0}", e);
		}
		
		String pawnBinding = PLAYER_BIND_PREFIX + session.getName() + "." + pawnName;
		
		DataManager dataMgr = AppContext.getDataManager();
		
		Pawn pawn;
		
		try
		{
			pawn = (Pawn)dataMgr.getBinding(pawnBinding);
		} catch(NameNotBoundException ex)
		{
			pawn = new Pawn(pawnName);
			logger.log(Level.INFO, "New pawn created :{0}", pawn);
			dataMgr.setBinding(pawnBinding, pawn);
		}
		catch (ObjectNotFoundException  e)
		{
			pawn = new Pawn(pawnName);
			logger.log(Level.INFO, "New pawn created :{0}", pawn);
			dataMgr.setBinding(pawnBinding, pawn);
		}
		pawn.setName(pawnName);
		Player player = new Player(session.getName());
		player.setPawn(pawn);
		player.setSession(session);
		
		return player;
	}
	
	protected Player(String name)
	{
		this.name = name;
	}

	public int getID()
	{
		return playerID;
	}
	
	protected void setPawn(Pawn pawn)
	{
		DataManager dataMgr = AppContext.getDataManager();
		
		if (pawn == null)
		{
			this.currentPawnRef = null;
			return;
		}
		this.currentPawnRef = dataMgr.createReference(pawn);
		logger.log(Level.INFO, "Set pawn for {0} to {1}", new Object[]{this, this.getID()});
	}
	
	protected Pawn getPawn()
	{
		if (this.currentPawnRef == null)
			return null;
		
		return this.currentPawnRef.get();
	}
	
	protected void setSession(ClientSession session)
	{
		DataManager dataMgr = AppContext.getDataManager();
		
		if (session == null)
		{
			this.currentSessionRef = null;
			return;
		}
		this.currentPawnRef.get().setSession(session);
		this.currentSessionRef = dataMgr.createReference(session);
		logger.log(Level.INFO, "Set session for {0} to {1}", new Object[]{this, this.getID()});
	}
	
	protected ClientSession getSession()
	{
		if (this.currentSessionRef == null)
			return null;
		
		return this.currentSessionRef.get();
	}
	
	/** {@inheritDoc} */
	public void receivedMessage(ByteBuffer message)
	{
		this.currentPawnRef.get().receivedMessage(message);
	}
	
	/** {@inheritDoc} */
	public void disconnected(boolean graceful)
	{
		this.getPawn().leave();
		setSession(null);
		logger.log(Level.INFO, "disconnected {0}", this);
		this.setWorld(null);
		this.setPawn(null);
	}
	
	protected World getWorld()
	{
		if (this.currentWorldRef == null)
			return null;
		
		return this.currentWorldRef.get();
	}
	
	protected void setWorld(World world)
	{
		if (world == null)
		{
			this.currentWorldRef = null;
			return;
		}

		DataManager dataMgr = AppContext.getDataManager();
		ByteBuffer buf = ByteBuffer.allocate(128);
		buf.putShort(PlayerProtocol.NET_CREATE_WORLD);
		buf.putLong(world.getID().getMostSignificantBits());
		buf.putLong(world.getID().getLeastSignificantBits());
		buf.flip();

		this.getSession().send(buf);
		
		this.currentPawnRef.get().enter(world);
		this.currentWorldRef = dataMgr.createReference(world);
	}

	//@Override
	public String toSting()
	{
		StringBuilder buf = new StringBuilder(this.name);
		buf.append('@');
		if (getSession() == null)
		{
			buf.append("null");
		}
		else
		{
			buf.append(this.currentSessionRef.getId());
		}
		
		return buf.toString();
		
	}
	
	protected static ByteBuffer encodeString(String string)
	{
		try
		{
			return ByteBuffer.wrap(string.getBytes(MESSAGE_CHARSET));
		}
		catch (UnsupportedEncodingException ex)
		{
			throw new Error("Request character set " + MESSAGE_CHARSET + "not found", ex);
		}
	}
	
	protected static String decodeString(ByteBuffer message)
	{
		try
		{
			byte[] bytes = new byte[message.remaining()];
			message.get(bytes);
			return new String(bytes, MESSAGE_CHARSET);
		}
		catch (UnsupportedEncodingException ex)
		{
			throw new Error("Request character set " + MESSAGE_CHARSET + "not found", ex);
		}
	}
}
